package com.juyu.miliao.api.service;

import com.alibaba.fastjson.JSONObject;
import com.juyu.miliao.api.dao.mysql.GradeDao;
import com.juyu.miliao.api.dao.mysql.UserInfoDao;
import com.juyu.miliao.api.dao.redis.LineTimeRedisDao;
import com.juyu.miliao.api.dao.redis.MakeFriendsRedisDao;
import com.juyu.miliao.api.dao.redis.UserCallRedisDao;
import com.juyu.miliao.api.dao.redis.UserRedisDao;
import com.juyu.miliao.api.domain.Grade;
import com.juyu.miliao.api.domain.User;
import com.juyu.miliao.api.domain.dto.IntegralLevelAndTitleDTO;
import com.juyu.miliao.api.domain.dto.UserCallUpdateDTO;
import com.juyu.miliao.api.util.ComputeRedPacketUtil;
import com.juyu.miliao.api.util.GradeUtil;
import com.juyu.miliao.api.util.RandomUtil;
import com.juyu.miliao.common.exception.ConsumeRuntimeException;
import com.juyu.miliao.common.exception.IllegalParamException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

@Service
@Slf4j
public class UserCallService {

    @Resource
    private UserInfoDao userInfoDao;
    @Resource
    private UserCallRedisDao userCallRedisDao;
    @Resource
    private LineTimeRedisDao lineTimeRedisDao;
    @Resource
    private AppKeyService appkeyService;

    @Autowired
    private GradeDao gradeDao;

    @Autowired
    private UserRedisDao userRedisDao;

    @Autowired
    private MakeFriendsRedisDao makeFriendsRedisDao;
    @Resource
    private IntegralLevelInfoService integralLevelInfoService;

    /**
     * 主播通话状态
     * @param type 1开始通话  2结束通话
     * @param userId 主播id
     */
    //	@Transactional(rollbackFor = Exception.class)
    public void userCallInfo(Integer type, long userId) {
        User user = userInfoDao.getUserById(userId);
        Optional<User> optUser = Optional.ofNullable(user);
        if (!optUser.isPresent()) {
            throw new IllegalParamException("用户不存在");
        }
        if (user.getIsHost() != 1)
            throw new IllegalParamException("用户不是主播");
        if (type == 1) {
            userCallRedisDao.startHostCall(userId);
            //从在线redis中删除该用户
//            lineTimeRedisDao.deleteHostLine(user.getUserId()+"");
//            lineTimeRedisDao.deleteLine(user.getUserId()+"");
//            lineTimeRedisDao.deleteOnLineUserBySex(user.getSex(),user.getUserId()+"");
        } else {
            userCallRedisDao.endHostCall(userId);
            //从在线redis中添加该用户
//            lineTimeRedisDao.addHostLine(user.getUserId()+"");
//            lineTimeRedisDao.addLine(user.getUserId()+"",String.valueOf(System.currentTimeMillis()));
//            lineTimeRedisDao.addHostLineBySex(user.getSex(),user.getUserId()+"");
        }
    }


    public String getUserCall() {
        //获取在线主播
        Set<String> userIdSet = lineTimeRedisDao.getHostLine();
        if (userIdSet.size() == 0)
            return "";
        List<Long> userList = new ArrayList<Long>();
        //判断在线主播是否通话中
        for (String userId : userIdSet) {
            if (!userCallRedisDao.findHostCall(userId))
                userList.add(Long.parseLong(userId));
        }
        if (userList.size() == 0)
            return "";
        List<User> user = userInfoDao.getUserListByUserIds(userList);
        //在线主播不能为视频勿扰
        user = user.stream().filter(i -> i.getIsVideo() != 2).collect(Collectors.toList());
        if (user.size() == 0)
            return "";
        //随机返回前端一个在线、未通话主播id
        int temp = ComputeRedPacketUtil.getRandom(0, user.size() - 1);
        return user.get(temp).getUserId() + "";
    }

    /**
     * @param userId
     * @param type   类型，1：在线，2：同城
     * @return
     */
    public Map<String, Object> getUserCallList(long userId, int type) {
        Map<String, Object> resultMap = new HashMap<>(1);
        User user = userInfoDao.getUserInfoById(userId);
        log.info("user:"+JSONObject.toJSONString(user));
        if (user.getIsHost() != 1) {
            throw new ConsumeRuntimeException("用户没有使用此功能权限");
        }

//        if (user.getStar() < 1) {
//            throw new ConsumeRuntimeException("只有1星以上的主播才可以打招呼");
//        }

        //根据用户魅力等级查询发送次数
//        List<Grade> mgradeList = gradeDao.getGrade(1);
//        Grade grade = GradeUtil.getGradeInfoByCount(mgradeList, user.getmGradeSum());
//        log.info(JSONObject.toJSONString(grade));
        int greetNum = 0;
        IntegralLevelAndTitleDTO userIntegralLevel =
                integralLevelInfoService.getUserIntegralLevel(user.getIntegralSum());
        if (userIntegralLevel.getGreetNum() != null) {
            greetNum = userIntegralLevel.getGreetNum();
        }


        //获取用户已打招呼的次数
        int userGreetNum = userCallRedisDao.getGreetNumByUserId(user.getUserId(), LocalDate.now(), type);
        //获取主播剩余打招呼次数
        int callNumber = greetNum - userGreetNum;
        if(callNumber<0){
            callNumber = 0;
        }
        int findSex = 1;

        if (user.getSex() == 1) {
            findSex = 2;
        }

        if (type == 1) {
            return getOnlineUserCallInfo(resultMap, user, callNumber, findSex);
        } else {
            return getSameCityUserCallInfo(resultMap, user, callNumber);

        }


    }

    /**
     * 获取同城列表中的打招呼用户
     *
     * @param resultMap
     * @param user
     * @param callNumber
     * @return
     */
    private Map<String, Object> getSameCityUserCallInfo(Map<String, Object> resultMap, User user, int callNumber) {
        List<String> userIdList = makeFriendsRedisDao.getSameCityList(user, 1, 120);
        if (userIdList.size() == 0) {
            resultMap.put("callNumber", callNumber);
            resultMap.put("data", new ArrayList<>());
            return resultMap;
        } else {
            Set<String> callUserSet = userCallRedisDao.getCallUserSet(user.getUserId(), LocalDate.now());
            userIdList.removeAll(callUserSet);
            if (userIdList.size() == 0) {
                resultMap.put("callNumber", callNumber);
                resultMap.put("data", new ArrayList<>());
                return resultMap;
            } else {
                if (userIdList.size() <= 9) {
                    List<Long> cids = userIdList.stream().map(Long::parseLong).collect(toList());
                    List<User> userList = userInfoDao.getQualityOnLineUserByUserIds(cids);
                    return getUserCallInfo(resultMap, callNumber, userList);
                } else {
                    int[] randoms = RandomUtil.randomCommon(0, userIdList.size(), 9);
                    List<Long> queryUserIdList = new ArrayList<>();
                    for (int i : randoms) {
                        queryUserIdList.add(Long.parseLong(userIdList.get(i)));
                    }
                    List<User> userList = userInfoDao.getQualityOnLineUserByUserIds(queryUserIdList);
                    return getUserCallInfo(resultMap, callNumber, userList);
                }
            }
        }
    }

    /**
     * 获取在线列表中的打招呼用户
     *
     * @param resultMap
     * @param user
     * @param callNumber
     * @param findSex
     * @return
     */
    private Map<String, Object> getOnlineUserCallInfo(Map<String, Object> resultMap, User user, int callNumber, int findSex) {
        Set<String> userIds = userRedisDao.findOnLineUserBySex(findSex, 0, 10000);
        if (userIds.size() == 0) {
            resultMap.put("callNumber", callNumber);
            resultMap.put("data", new ArrayList<>());
            return resultMap;
        } else {
            Set<String> callUserSet = userCallRedisDao.getCallUserSet(user.getUserId(), LocalDate.now());
            userIds.removeAll(callUserSet);
            if (userIds.size() == 0) {
                resultMap.put("callNumber", callNumber);
                resultMap.put("data", new ArrayList<>());
                return resultMap;
            } else {
                if (userIds.size() <= 9) {
                    log.info("userIds="+JSONObject.toJSONString(userIds));
                    List<Long> cids = userIds.stream().map(Long::parseLong).collect(toList());
                    log.info("queryUserIds="+JSONObject.toJSONString(cids));
                    List<User> userList = userInfoDao.getQualityOnLineUserByUserIds(cids);
                    return getUserCallInfo(resultMap, callNumber, userList);
                } else {

                    int[] randoms = RandomUtil.randomCommon(0, userIds.size(), 9);
                    log.info("randoms="+JSONObject.toJSONString(randoms));
                    List<String> targetList = new ArrayList<>(userIds);
                    List<Long> queryUserIdList = new ArrayList<>();
                    for (int i : randoms) {
                        String value = targetList.get(i);
                        queryUserIdList.add(Long.parseLong(value));
                    }
                    log.info("queryUserIdList="+JSONObject.toJSONString(queryUserIdList));
                    List<User> userList = userInfoDao.getQualityOnLineUserByUserIds(queryUserIdList);
                    return getUserCallInfo(resultMap, callNumber, userList);
                }
            }
        }
    }

    /**
     * 设置返还信息
     *
     * @param resultMap
     * @param callNumber
     * @param userList
     * @return
     */
    private Map<String, Object> getUserCallInfo(Map<String, Object> resultMap, int callNumber,
                                                List<User> userList) {
        List<Map<String, Object>> data = new ArrayList<>();
        for (User obj : userList) {
            Map<String, Object> userMap = new HashMap<>(4);
            userMap.put("userId", obj.getUserId());
            userMap.put("icon", obj.getIcon());
            if (obj.getNickName().length() > 4) {
                userMap.put("nickName", obj.getNickName().substring(0, 4) + "...");
            } else {
                userMap.put("nickName", obj.getNickName());
            }
            userMap.put("isVip", obj.getIsVip());
            userMap.put("isHost", obj.getIsHost());
//            userMap.put("star", obj.getStar());
            userMap.put("vipLevel", obj.getVipLevel());
            data.add(userMap);
        }
        resultMap.put("callNumber", callNumber);
        resultMap.put("data", data);
        return resultMap;
    }

    /**
     * 更新打招呼次数
     *
     * @param userId
     * @param userCallUpdateDTO
     */
    public void updateCallNumber(long userId, UserCallUpdateDTO userCallUpdateDTO) {
        LocalDateTime localDateTime = LocalDateTime.now();
        List<String> userIdList = new ArrayList<>();
        List<String> targetList = userCallUpdateDTO.getUserIds();
        for (String id : targetList) {
            boolean bl = userCallRedisDao.checkUserId(userId, id);
            if (!bl) {
                userIdList.add(id);
            }
        }

        if (userIdList.size() > 0) {
            userCallRedisDao.setCallUserSet(userId, localDateTime, userIdList);
            userCallRedisDao.incrementCallUserNumber(userId, localDateTime, userCallUpdateDTO.getType());
        }
    }
}
